#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define PORT 8080
#define BUFFER_SIZE 1024

void set_nonblocking(int sockfd) {
	    int flags = fcntl(sockfd, F_GETFL, 0);
	        if (flags == -1) {
			        perror("fcntl F_GETFL");
				        exit(EXIT_FAILURE);
					    }
		    if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1) {
			            perror("fcntl F_SETFL");
				            exit(EXIT_FAILURE);
					        }
}

int main() {
	    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	        if (sockfd == -1) {
			        perror("socket");
				        exit(EXIT_FAILURE);
					    }


		    set_nonblocking(sockfd);

		        struct sockaddr_in serv_addr;
			    memset(&serv_addr, 0, sizeof(serv_addr));
			        serv_addr.sin_family = AF_INET;
				    serv_addr.sin_port = htons(PORT);
				        inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);

					    int ret = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
					        if (ret == -1) {
							        if (errno == EINPROGRESS) {
									            printf("Connect is in progress, doing other work...\n");
										                
										                fd_set writefds;
												            FD_ZERO(&writefds);
													                FD_SET(sockfd, &writefds);
															            
															            struct timeval timeout;
																                timeout.tv_sec = 5;
																		            timeout.tv_usec = 0;
																			                
																			                ret = select(sockfd + 1, NULL, &writefds, NULL, &timeout);
																					            if (ret <= 0) {
																							                    perror("select");
																									                    close(sockfd);
																											                    exit(EXIT_FAILURE);
																													                }
																						                int error = 0;
																								            socklen_t len = sizeof(error);
																									                if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
																												                perror("getsockopt");
																														                close(sockfd);
																																                exit(EXIT_FAILURE);
																																		            }
																											            
																											            if (error != 0) {
																													                    fprintf(stderr, "Connection failed: %s\n", strerror(error));
																															                    close(sockfd);
																																	                    exit(EXIT_FAILURE);
																																			                }
																												                
																												                printf("Connection established successfully\n");
																														        } else {
																																            perror("connect");
																																	                close(sockfd);
																																			            exit(EXIT_FAILURE);
																																				            }
								    }

						    char buffer[BUFFER_SIZE] = "Hello, Server!";
						        ret = send(sockfd, buffer, strlen(buffer), 0);
							    if (ret == -1) {
								            if (errno == EAGAIN || errno == EWOULDBLOCK) {
										                printf("Send would block, try again later\n");
												        } else {
														            perror("send");
															                close(sockfd);
																	            exit(EXIT_FAILURE);
																		            }
									        } else {
											        printf("Sent %d bytes: %s\n", ret, buffer);
												    }

							        close(sockfd);
								    return 0;
}
